#include "Goal_TakePathToRange.h"
#include "Goal_Types.h"
#include "Steering Behavior.h"
#include "MessageTypes.h"
#include "Message.h"


/////////////////////////////////////// Constructors \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

/*! Constructor1
	====================================================
	\param Owner: The character that owns this instance
	\param Dest: The location that the character is going 
					towards
	\param Range: The distance that the character must get
					from the destination.
	\param CheckDisabled: Whether or not the character is
							allowed to move across water.
*/

Goal_TakePathToRange::Goal_TakePathToRange(Character* owner, Vector2D dest, double range, Permissions perm): Goal_Composite(owner, goal_take_path_to_location)
{
	m_pPath = new Path(m_pOwner->Pos(),dest, perm);	

	if(!m_pPath->IsValid())
	{
		delete m_pPath;
		m_pPath = new Path(m_pOwner->Pos(), dest, perm);
	}

	m_dRange = range;

	if(m_dRange < sqrt(SteeringBehavior::m_dWaypointSeekDistSq))
		m_dRange = sqrt(SteeringBehavior::m_dWaypointSeekDistSq);
}

/*! Constructor 2
	=====================================================
	Same as above, but takes a pregenerated path instead.
*/

Goal_TakePathToRange::Goal_TakePathToRange(Character* owner, Path* path, double range) : Goal_Composite(owner, goal_take_path_to_location)
{
	m_pPath = path;
	m_dRange = range;

	if(m_dRange < sqrt(SteeringBehavior::m_dWaypointSeekDistSq))
		m_dRange = sqrt(SteeringBehavior::m_dWaypointSeekDistSq);

}

/*! Activate()
	===============================================
	Activates this goal. Sets the steering behavior
	of the owner to FollowPath and sets it's path
	to this instances path.
*/

void Goal_TakePathToRange::Activate()
{
	m_iStatus = active;
	m_pOwner->m_pSteeringBehavior->SetPath(m_pPath);
	m_pOwner->m_pSteeringBehavior->FollowPathOn();
}

/*! Process
	==============================================
	Processes the goal. Activates the goal if it
	is inactive. Checks to see whether or not the 
	character has come within the range of the 
	destination. Also, if the character receives
	a new goal while walking, the path will be 
	deleted, and this goal will return failure.
*/

int Goal_TakePathToRange::Process()
{
	ActivateIfInactive();

	// This merely checks to see if the character has reached the last way point,
	// the actual implementation of following the path is in SteeringBehaviors::FollowPath

	if(m_pPath != NULL)
	{
		if(m_pPath->IsValid())
		{
			if(m_pOwner->Pos().DistanceSq(m_pPath->lastPoint()) < m_dRange*m_dRange)
				this->m_iStatus = completed;
		}
		else
			this->m_iStatus = failed;
	}
			

	return 0;
}

/*! Terminate
	===========================================
	Turns off the follow path steering behavior
	of the owner. (Which actually takes care 
	of freeing the memory if you're nitpicky)

*/
void Goal_TakePathToRange::Terminate()
{
	m_pOwner->m_pSteeringBehavior->FollowPathOff();
	m_pPath = NULL;
}

/*! HandleMessage
	============================================
	When a message is received involving moving 
	somewhere else, it sets the status of this
	one to failed. Can't move in two directions
	at once.
*/
bool Goal_TakePathToRange::HandleMessage(const Message &msg)
{
	if(msg.Type == MoveToLocation)
	{
		m_iStatus = failed;
		return true;
	}
	if(msg.Type == Follow_Offset_Path)
	{
		m_iStatus = failed;
		return true;
	}

	return false;
}